package com.yunxin.core.application.service.impl;

import cn.hutool.core.text.CharSequenceUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.yunxin.common.result.PageResult;
import com.yunxin.common.utils.JacksonUtils;
import com.yunxin.core.application.assembler.PopupAssembler;
import com.yunxin.core.application.command.popup.PopupPageCommand;
import com.yunxin.core.application.command.popup.ProductOptionsCommand;
import com.yunxin.core.application.dto.popup.PopupListDTO;
import com.yunxin.core.application.dto.popup.PopupPageDTO;
import com.yunxin.core.application.dto.popup.PopupProductsDTO;
import com.yunxin.core.application.dto.popup.ProductOptionsDTO;
import com.yunxin.core.application.service.PopupQueryAdminService;
import com.yunxin.core.domain.external.product.ProductExternalService;
import com.yunxin.core.domain.external.product.ProductFromPopupDetail;
import com.yunxin.core.domain.external.product.ProductOption;
import com.yunxin.core.infra.common.product.enums.ProductAbutmentTypeEnum;
import com.yunxin.core.infra.common.product.enums.ProductBusinessSceneEnum;
import com.yunxin.core.infra.common.product.enums.ProductStatusEnum;
import com.yunxin.core.infra.persistence.entity.popup.PopupDO;
import com.yunxin.core.infra.persistence.entity.popup.query.condition.PopupPageCondition;
import com.yunxin.core.infra.persistence.mapper.popup.PopupExtendMapper;
import com.yunxin.core.infra.persistence.mapper.popup.PopupProductConfigExtendMapper;
import com.yunxin.core.utils.infra.common.constant.CommonConstants;
import com.yunxin.core.utils.infra.utils.PageQueryUtils;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author zero°
 * @since 2023-12-11
 */
@Service
@RequiredArgsConstructor
public class PopupQueryAdminServiceImpl implements PopupQueryAdminService {

    private final PopupExtendMapper popupExtendMapper;

    private final PopupProductConfigExtendMapper popupProductConfigExtendMapper;

    private final PopupAssembler popupAssembler;

    private final ProductExternalService productExternalService;

    @Override
    public PageResult<PopupPageDTO> page(PopupPageCommand command) {
        PopupPageCondition condition = popupAssembler.fromPopupPageCommand(command);
        long total = popupExtendMapper.countPopupPageQuery(condition);
        if (total == 0) {
            return PageResult.success(Collections.emptyList(), total);
        }
        condition.setOffset(PageQueryUtils.X.getOffset(command.getPageNum(), command.getPageSize()));
        List<PopupDO> results = popupExtendMapper.popupPageQuery(condition);
        List<PopupPageDTO> dtoList = results.stream().map(popupAssembler::toPopupPageDTO).toList();
        return PageResult.success(dtoList, total);
    }

    @Override
    public List<PopupListDTO> list() {
        List<PopupDO> recommendedPopupDos = popupExtendMapper.list();
        return recommendedPopupDos.stream().map(popupAssembler::toPopupListDTO).toList();
    }

    @Override
    public ProductOptionsDTO productOptions(ProductOptionsCommand command) {
        ProductOptionsDTO productOptionsDTO = new ProductOptionsDTO();
        productOptionsDTO.setId(command.getId());
        List<ProductOption> productOptionList = productExternalService.getProductOptionList(ProductStatusEnum.GROUNDING.getValue(),
                ProductAbutmentTypeEnum.H5.getValue(), List.of(ProductBusinessSceneEnum.UV.getValue(),ProductBusinessSceneEnum.REGISTER.getValue()));
        if(CollectionUtils.isEmpty(productOptionList)){
            productOptionsDTO.setProductList(Collections.emptyList());
            return productOptionsDTO;
        }
        String productData = popupProductConfigExtendMapper.getLastPopupProductData(command.getId(), null);
        if (CharSequenceUtil.isNotEmpty(productData)) {
            List<Long> productIds = JacksonUtils.X.parse(productData, new TypeReference<>() {});
            if(!CollectionUtils.isEmpty(productIds)){
                productOptionList = productOptionList.stream().filter(x -> !productIds.contains(x.getId())).toList();
            }
        }
        List<ProductOptionsDTO.Product> products = productOptionList.stream().map(x -> {
            ProductOptionsDTO.Product product = new ProductOptionsDTO.Product();
            product.setProductId(x.getId());
            product.setProductName(x.getProductName());
            return product;
        }).toList();
        productOptionsDTO.setProductList(products);
        return productOptionsDTO;
    }

    @Override
    public PopupProductsDTO queryProductList(ProductOptionsCommand command) {
        PopupProductsDTO popupProductsDTO = new PopupProductsDTO();
        popupProductsDTO.setId(command.getId());
        String productData = popupProductConfigExtendMapper.getLastPopupProductData(command.getId(), null);
        popupProductsDTO.setProductList(Collections.emptyList());
        if(CharSequenceUtil.isEmpty(productData)){
            return popupProductsDTO;
        }
        List<Long> productIds = JacksonUtils.X.parse(productData, new TypeReference<>() {});
        if(CollectionUtils.isEmpty(productIds)){
            return popupProductsDTO;
        }
        List<ProductFromPopupDetail> list = productExternalService.listProductDetailsByIds(productIds);
        if(CollectionUtils.isEmpty(list)){
            return popupProductsDTO;
        }
        Map<Long, ProductFromPopupDetail> productMap = list.stream().collect(Collectors.toMap(ProductFromPopupDetail::getProductId, Function.identity()));
        List<PopupProductsDTO.Product> products = productIds.stream().map(x -> {
            PopupProductsDTO.Product product = new PopupProductsDTO.Product();
            Optional.ofNullable(productMap.get(x)).ifPresent(y -> {
                product.setProductId(y.getProductId());
                product.setMerchantName(y.getMerchantName());
                product.setProductName(y.getProductName());
                product.setProductImage(y.getProductImage());
                product.setProductLabeling(Optional.ofNullable(y.getProductLabeling()).filter(StringUtils::isNotBlank).map(l -> Arrays.asList(l.split(CommonConstants.COMMA))).orElse(Collections.emptyList()));
                product.setValid(y.getValid());
            });
            return product;
        }).toList();
        popupProductsDTO.setProductList(products);
        return popupProductsDTO;
    }
}
